#include "stdafx.h"

#include "../CmdLineProc/CmdLineProc.h"

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;

namespace CmdLineProcTest
{
	[TestClass]
	public ref class UnitTest1
	{
	private:
		TestContext^ testContextInstance;

	public: 
		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext
		{
			Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get()
			{
				return testContextInstance;
			}
			System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value)
			{
				testContextInstance = value;
			}
		};

		#pragma region Additional test attributes
		//
		//You can use the following additional attributes as you write your tests:
		//
		//Use ClassInitialize to run code before running the first test in the class
		//[ClassInitialize()]
		//static void MyClassInitialize(TestContext^ testContext) {};
		//
		//Use ClassCleanup to run code after all tests in a class have run
		//[ClassCleanup()]
		//static void MyClassCleanup() {};
		//
		//Use TestInitialize to run code before running each test
		//[TestInitialize()]
		//void MyTestInitialize() {};
		//
		//Use TestCleanup to run code after each test has run
		//[TestCleanup()]
		//void MyTestCleanup() {};
		//
		#pragma endregion 

		[TestMethod]
		void CommandLineTest1()
		{
			CmdLineProc cl;

			vector<string> parsed = cl.Parse(" Test this    string! ");

			Assert::AreEqual((int)parsed.size(), (int)3, "Invalid number of parsed parts");
			Assert::IsTrue(parsed[0] == string("Test"), "First word incorrect.");
			Assert::IsTrue(parsed[1] == string("this"), "Second word incorrect.");
			Assert::IsTrue(parsed[2] == string("string!"), "Third word incorrect.");
		};

		[TestMethod]
		void CommandLineTest2()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false, string("cDefult"));
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			try
			{
				cl.LoadCommandString(string("-a=aOption -a=aOptionSecond  -d   -e -b=bOption")); 
			}
			catch (string* str)
			{
				Console::WriteLine(gcnew System::String(str->c_str()));
			}

			vector<string> m;
			cl.GetValue(string("-a"), m);
			Assert::IsTrue(m[0] == string("aOption"));
			Assert::IsTrue(m[1] == string("aOptionSecond"));

			Assert::IsTrue(cl.GetValue(string("-b")) == string("bOption"));
			Assert::IsTrue(cl.GetFlag(string("-d")));
			Assert::IsTrue(cl.GetFlag(string("-e")));
			Assert::IsFalse(cl.GetFlag(string("-t")));

			Assert::IsTrue(cl.IsSupplied("-a"));
			Assert::IsTrue(cl.IsSupplied("-d"));
			Assert::IsFalse(cl.IsSupplied("-k"));
			Assert::IsFalse(cl.IsSupplied("-f"));
			
		};

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineMissingOption()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string(" -d   -e -b=bOption")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineMissingFlag()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a=aOptionSecond  -e -b=bOption")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineDuplicateFlag()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a=aOptionSecond -d  -e -b=bOption -d")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineDuplicateOption()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a=aOptionSecond -d  -e -b=bOption -b=bOption2")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineInvalidOption()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a=aOptionSecond -d  -e -k=bOption ")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineOptionAsFlag()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a=aOptionSecond -d -a  -e ")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void CommandLineMissingOptionValue()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false);
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a= -d  -e ")); 

			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		void CommandLineGetUsageTest()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, true);		
			cl.AddOption(string("-b"), string("B something"), true, false);
			cl.AddOption(string("-c"), string("C something"), false, false, string("cDefult"));
			cl.AddFlag(string("-d"), string("D something"), true);
			cl.AddFlag(string("-e"), string("E something"), false);

			cl.LoadCommandString(string("-a=aOption -a=aOptionSecond  -d   -e -b=bOption")); 

			string s = cl.GetUsage();
			Console::Write(gcnew String(s.c_str()));
		}

		[TestMethod]
		[ExpectedException(System::Runtime::InteropServices::SEHException::typeid)]
		void DefaultNotSetTest()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, false);
			cl.AddOption(string("-b"), string("B something"), false, false);
			cl.AddOption(string("-c"), string("C something"), true, false);
			Assert::Fail("Expected exception to be thrown.");
		}

		[TestMethod]
		void DefaultValueTest()
		{
			CmdLineProc cl;

			cl.AddOption(string("-a"), string("A something"), true, false);
			cl.AddOption(string("-b"), string("B something"), false, false, string("10"));
			cl.AddOption(string("-c"), string("C something"), true, false);
			cl.AddOption(string("-d"), string("D something"), false, false, string("20"));
			cl.AddOption(string("-e"), string("E something"), false, true, string("30"));

			cl.LoadCommandString(string("-a=aOption -c=cOption -d=25"));

			Assert::AreEqual(10, atoi(cl.GetValue("-b").c_str()));
			Assert::AreEqual(25, atoi(cl.GetValue("-d").c_str()));
			Assert::AreEqual(30, atoi(cl.GetValue("-e").c_str()));
		}
	};
}
